//
// Created by liuyang on 2025/5/21.
//

#include "log.h"

namespace sylar{
    const char *LogLevel::Tostring(LogLevel::Level level) {
        switch (level) {
            case LogLevel::DEBUG:
                return "DEBUG";
            case LogLevel::INFO:
                return "INFO";
            case LogLevel::WARN:
                return "WARN";
            case LogLevel::ERROR:
                return "ERROR";
            case LogLevel::FATAL:
                return "FATAL";
            default:
                return "UNKNOWN";
        }
    }

Logger::Logger(const std::string &name) {
    m_name=name;
}

void Logger::log(LogLevel::Level level, LogEvent::ptr event) {
    if(level>=m_level){
        for(auto& i:m_logAppenders){
            i->log(level,event);
        }
    }
}
void Logger::debug(LogEvent::ptr event) {
    log(LogLevel::DEBUG,event);
};
void Logger::warn(LogEvent::ptr event) {
    log(LogLevel::WARN,event);
};
void Logger::error(LogEvent::ptr event) {
    log(LogLevel::ERROR,event);
};
void Logger::fatal(LogEvent::ptr event) {
    log(LogLevel::FATAL,event);
};

void Logger::addAppender(LogAppender::ptr  appender){
    m_logAppenders.push_back(appender);
};
void Logger::delAppender(LogAppender::ptr appender){
    for(auto it=m_logAppenders.begin();it!=m_logAppenders.end();++it){
        if(*it==appender){
            m_logAppenders.erase(it);
            break;
        }
    }
};

bool FileLogAppender::reopen() {
    if(m_filestream){
        m_filestream.close();
    }
    m_filestream.open(m_name);
    return !!m_filestream;
}

void FileLogAppender::log(LogLevel::Level level,LogEvent::ptr event){
    if(level>=m_level){
        m_filestream<<m_formatter->format(level,event);
    }
};

void StdoutLogAppender::log(LogLevel::Level level, LogEvent::ptr event) {
    if(level>=m_level){
        std::cout<<m_formatter->format(level,event);
    }
}

LogFormatter::LogFormatter(const std::string &pattern) {
    m_pattern=pattern;
}

//%xxx %xxx{xxx} %%
void LogFormatter::init() {
    //str, format, type
    std::vector<std::tuple<std::string, std::string, int> > vec;
    std::string nstr;
    for(size_t i = 0; i < m_pattern.size(); ++i) {
        if(m_pattern[i] != '%') {
            nstr.append(1, m_pattern[i]);
            continue;
        }

        if((i + 1) < m_pattern.size()) {
            if(m_pattern[i + 1] == '%') {
                nstr.append(1, '%');
                continue;
            }
        }

        size_t n = i + 1;
        int fmt_status = 0;
        size_t fmt_begin = 0;

        std::string str;
        std::string fmt;
        while(n < m_pattern.size()) {
            if(!fmt_status && (!isalpha(m_pattern[n]) && m_pattern[n] != '{'
                               && m_pattern[n] != '}')) {
                str = m_pattern.substr(i + 1, n - i - 1);
                break;
            }
            if(fmt_status == 0) {
                if(m_pattern[n] == '{') {
                    str = m_pattern.substr(i + 1, n - i - 1);
                    //std::cout << "*" << str << std::endl;
                    fmt_status = 1; //解析格式
                    fmt_begin = n;
                    ++n;
                    continue;
                }
            } else if(fmt_status == 1) {
                if(m_pattern[n] == '}') {
                    fmt = m_pattern.substr(fmt_begin + 1, n - fmt_begin - 1);
                    //std::cout << "#" << fmt << std::endl;
                    fmt_status = 0;
                    ++n;
                    break;
                }
            }
            ++n;
            if(n == m_pattern.size()) {
                if(str.empty()) {
                    str = m_pattern.substr(i + 1);
                }
            }
        }

        if(fmt_status == 0) {
            if(!nstr.empty()) {
                vec.push_back(std::make_tuple(nstr, std::string(), 0));
                nstr.clear();
            }
            vec.push_back(std::make_tuple(str, fmt, 1));
            i = n - 1;
        } else if(fmt_status == 1) {
            std::cout << "pattern parse error: " << m_pattern << " - " << m_pattern.substr(i) << std::endl;
            vec.push_back(std::make_tuple("<<pattern_error>>", fmt, 0));
        }else if(fmt_status==2){
             if(!nstr.empty()){
                 vec.push_back(std::make_tuple(nstr,"",0));
             }
             vec.push_back(std::make_tuple(str,fmt,1));
             i=n;
        }
    }
    if(!nstr.empty()){
        vec.push_back(std::make_tuple(nstr,"",0));
    }


}

class MessageFormatItem:public LogFormatter::FormatItem{
    virtual void format(std::ostream& os,LogLevel::Level level,LogEvent::ptr event) override{
        os<<event->getContent();
    }
};

class LevelFormatItem:public LogFormatter::FormatItem{
    virtual void format(std::ostream& os,LogLevel::Level level,LogEvent::ptr event) override{
        os<<LogLevel::Tostring(level);
    }
};



std::string LogFormatter::format(LogLevel::Level level,LogEvent::ptr event) {
    std::stringstream os;
    for(auto& i:m_items){
        i->format(os,level,event);
    }
    return os.str();
}

}
